fix(installer): use relative paths for hook commands in settings.local.json#7
fix(installer): use relative paths for hook commands in settings.local.json#7riaworks wants to merge 1 commit into
Conversation
…l.json The installer generated platform-specific hook commands that caused issues: - Windows: absolute paths with escaped backslashes (machine-dependent, fragile) - Unix: $CLAUDE_PROJECT_DIR variable (known bugs GH #6023/#5814) Both approaches led to UserPromptSubmit hook errors in installed projects. Changes: - Use relative path `node .claude/hooks/<file>` on all platforms - Remove hardcoded `timeout: 10` from HOOK_EVENT_MAP and generated settings (Claude Code manages hook timeouts natively, each hook has internal safety) - Remove unused `isWindows` and `hookFilePath` variables - Update tests to reflect timeout removal The HOOK_EVENT_MAP event routing (MIS-3.1) remains unchanged — precompact is correctly mapped to PreCompact, not UserPromptSubmit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WalkthroughTimeout configuration removed from hook settings to enable external management by Claude Code. Hook command paths changed from Windows-specific absolute paths to relative paths using the format Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📊 Coverage ReportCoverage report not available
Generated by PR Automation (Story 6.1) |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js (1)
177-177: Add exact command-path assertions to lock the PR’s core behavior.Nice update on timeout removal. One gap: these tests still don’t assert the exact hook command format (
node .claude/hooks/<file>), so an absolute-path regression could still pass.Suggested test hardening
const upsCommands = settings.hooks.UserPromptSubmit.flatMap(e => e.hooks.map(h => h.command)); expect(upsCommands.some(c => c.includes('synapse-engine'))).toBe(true); + expect(upsCommands).toContain('node .claude/hooks/synapse-engine.cjs'); // code-intel-pretool → PreToolUse with matcher expect(settings.hooks.PreToolUse).toBeDefined(); @@ const ptuCommands = settings.hooks.PreToolUse.flatMap(e => e.hooks.map(h => h.command)); expect(ptuCommands.some(c => c.includes('code-intel-pretool'))).toBe(true); + expect(ptuCommands).toContain('node .claude/hooks/code-intel-pretool.cjs'); @@ const pcCommands = settings.hooks.PreCompact.flatMap(e => e.hooks.map(h => h.command)); expect(pcCommands.some(c => c.includes('precompact-session-digest'))).toBe(true); + expect(pcCommands).toContain('node .claude/hooks/precompact-session-digest.cjs');Also applies to: 185-185, 193-193, 207-207
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js` at line 177, The test currently only checks timeout removal with expect(config.timeout).toBeUndefined(); strengthen it by adding exact command-path assertions for the hook(s): locate the same test block(s) where config is inspected (the lines containing expect(config.timeout).toBeUndefined()) and add assertions that the hook command string(s) equal the exact expected format "node .claude/hooks/<filename>" (for whichever property holds the hook, e.g., config.command or config.hooks[...].command); apply the same exact-path assertion to the other occurrences mentioned (the blocks around the other expect(config.timeout).toBeUndefined() checks at the same test file) so the test fails on any absolute-path regression.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/installer/src/wizard/ide-config-generator.js`:
- Around line 791-795: The current construction of hookCommand interpolates
hookFileName directly and is vulnerable to spaces or shell metacharacters;
instead sanitize or avoid the shell: validate hookFileName against a safe
pattern (e.g., allow only alphanumerics, dots, dashes, underscores) and/or
escape quotes/metacharacters in hookFileName, then either wrap the sanitized
name in quotes when building hookCommand or—preferably—stop using a single shell
string and invoke node with an argv array (e.g., use
child_process.spawn/execFile with arguments ['.claude/hooks/<sanitizedName>'])
so the value of hookFileName cannot be interpreted by the shell. Ensure changes
target the hookCommand construction that uses hookFileName.
---
Nitpick comments:
In
`@packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js`:
- Line 177: The test currently only checks timeout removal with
expect(config.timeout).toBeUndefined(); strengthen it by adding exact
command-path assertions for the hook(s): locate the same test block(s) where
config is inspected (the lines containing
expect(config.timeout).toBeUndefined()) and add assertions that the hook command
string(s) equal the exact expected format "node .claude/hooks/<filename>" (for
whichever property holds the hook, e.g., config.command or
config.hooks[...].command); apply the same exact-path assertion to the other
occurrences mentioned (the blocks around the other
expect(config.timeout).toBeUndefined() checks at the same test file) so the test
fails on any absolute-path regression.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/installer/src/wizard/ide-config-generator.jspackages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js
| // Use relative path — works on all platforms, no $CLAUDE_PROJECT_DIR bugs | ||
| // (GH #6023/#5814), no fragile absolute Windows paths with escaped backslashes. | ||
| // Claude Code resolves relative paths from the project root (cwd). | ||
| const hookCommand = `node .claude/hooks/${hookFileName}`; | ||
|
|
There was a problem hiding this comment.
Quote and sanitize hook filenames before building shell commands.
On Line 794, hookFileName is interpolated directly into a shell command. Filenames with spaces or shell metacharacters can break execution or cause command injection.
Proposed fix
- const hookFiles = allFiles.filter(f => f.endsWith('.cjs'));
+ const SAFE_HOOK_FILE_RE = /^[A-Za-z0-9._-]+\.cjs$/;
+ const hookFiles = allFiles.filter((f) => SAFE_HOOK_FILE_RE.test(f));
@@
- const hookCommand = `node .claude/hooks/${hookFileName}`;
+ const hookCommand = `node ".claude/hooks/${hookFileName}"`;As per coding guidelines, "Look for potential security vulnerabilities."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/installer/src/wizard/ide-config-generator.js` around lines 791 -
795, The current construction of hookCommand interpolates hookFileName directly
and is vulnerable to spaces or shell metacharacters; instead sanitize or avoid
the shell: validate hookFileName against a safe pattern (e.g., allow only
alphanumerics, dots, dashes, underscores) and/or escape quotes/metacharacters in
hookFileName, then either wrap the sanitized name in quotes when building
hookCommand or—preferably—stop using a single shell string and invoke node with
an argv array (e.g., use child_process.spawn/execFile with arguments
['.claude/hooks/<sanitizedName>']) so the value of hookFileName cannot be
interpreted by the shell. Ensure changes target the hookCommand construction
that uses hookFileName.
|
This pull request has been automatically marked as stale because it has not had |
Summary
node .claude/hooks/<file>)timeout: 10fromHOOK_EVENT_MAPand generatedsettings.local.jsonisWindowsandhookFilePathvariablesProblem
The installer generated different hook commands per platform:
node "C:\path\to\hooks\synapse-engine.cjs"node "$CLAUDE_PROJECT_DIR/.claude/hooks/synapse-engine.cjs"$CLAUDE_PROJECT_DIRhas known bugs (GH #6023/#5814)Both approaches caused
UserPromptSubmit hook errorin installed projects. Thetimeout: 10override was also unnecessary — Claude Code manages hook timeouts natively (default 60s), and each hook already has its own internal safety timeout.Fix
Single relative path for all platforms:
{ "type": "command", "command": "node .claude/hooks/synapse-engine.cjs" }Claude Code resolves relative paths from the project root (cwd), so this works everywhere.
Test plan
artifact-copy-pipeline.test.js)HOOK_EVENT_MAPstill correctly routes precompact → PreCompact (MIS-3.1)npx aios-core installgenerates correctsettings.local.json🤖 Generated with Claude Code
Summary by CodeRabbit